#ifndef ASYNCLAYER_H
#define ASYNCLAYER_H

#include <QPixmap>
#include <thread>
#include <mutex>
#include <memory>
#include <condition_variable>

class AsyncLayer
{
public:
    // 当 async == 1 时启用异步图层
    explicit AsyncLayer(int async = 0) :
        _async(async), stepRequested(false), stopRequested(false),
        _width(600), _height(600)
    {
        if (_async)
        {
            // 创建绘制线程
            _work_thread = std::make_unique<std::thread>(&AsyncLayer::work, this);
        }
    }

    virtual ~AsyncLayer()
    {
        // 通知绘制结束
        stop();

        // 如果绘制线程存在且在工作，等待结束
        if (_work_thread && _work_thread->joinable())
        {
            _work_thread->join();
        }
    }

    bool isAsync()
    {
        return (_async == 1) ? true : false;
    }

protected:
    virtual void draw(QPixmap& pixmap) = 0;

private:
    // 异步标志
    const int _async;

    // 绘制请求信号
    bool stepRequested;
    // 结束绘制信号
    bool stopRequested;

    // 信号保护锁
    std::mutex _signal_mutex;
    // 信号触发器
    std::condition_variable _signal_cond;
    // 绘制子线程
    std::unique_ptr<std::thread> _work_thread;

    // 绘制区宽度 & 高度
    int _width, _height;
    // 绘制区宽高保护锁
    std::mutex _wh_mutex;

    // 绘制结果
    QPixmap _pixmap;
    // 绘制结果保护锁
    std::mutex _pix_mutex;

    void work()
    {
        if (isAsync())
        {
            // 异步模式下，通过循环-信号量连续触发
            while (!stopRequested)
            {
                {
                    // 等待唤醒
                    std::unique_lock<std::mutex> lock(_signal_mutex);
                    _signal_cond.wait(lock, [this]{ return stepRequested or stopRequested; });

                    // 结束主循环
                    if (stopRequested) break;

                    // 重置绘图请求信号
                    stepRequested = false;
                }

                int width, height;
                {
                    std::unique_lock<std::mutex> lock(_wh_mutex);
                    width  = _width;
                    height = _height;
                }

                // 创建空白图层
                QPixmap pixmap(width, height);
                pixmap.fill(Qt::transparent);

                // 调用用户绘图接口
                draw(pixmap);

                // 更新绘制结果
                {
                    std::unique_lock<std::mutex> lock(_pix_mutex);
                    _pixmap.swap(pixmap);
                }
            }
        }
        else
        {   // 同步模式下通过step函数单步触发
            // 创建空白图层
            QPixmap pixmap(_width, _height);
            pixmap.fill(Qt::transparent);

            // 调用用户绘图接口
            draw(pixmap);

            // 更新绘制结果
            _pixmap.swap(pixmap);
        }
    }

    void step(int width, int height)
    {
        if (isAsync())
        {
            {
                // 更新绘图区宽高
                std::unique_lock<std::mutex> lock(_wh_mutex);
                _width  = width;
                _height = height;
            }

            {
                // 触发绘图信号
                std::unique_lock<std::mutex> lock(_signal_mutex);
                stepRequested = true;
            }

            // 唤醒绘图线程
            _signal_cond.notify_one();
        }
        else
        {
            _width  = width;
            _height = height;

            // 同步模式下直接调用
            work();
        }
    }

    void stop()
    {
        if (isAsync())
        {
            {
                std::unique_lock<std::mutex> lock(_signal_mutex);
                stopRequested = true;
            }
            _signal_cond.notify_all();
        }
    }

    friend class Composer;
};

#endif // ASYNCLAYER_H
